﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using EuroManager.Domain.Simulator.Engine;
using EuroManager.Domain.Simulator.Helpers;

namespace EuroManager.Domain.Simulator.World
{
    public class GameWorld : IGameWorld
    {
        private List<ITimeAware> timeAwares = new List<ITimeAware>();
        private bool isFinished = false;
        private TimeSpan totalRealTime;
        private TimeSpan totalGameTime = TimeSpan.FromMinutes(90);

        private Clock clock;
        private IPitch pitch;
        private IBall ball;
        private ITeam team1;
        private ITeam team2;

        public GameWorld(TimeSpan totalRealTime)
        {
            Contract.Requires(totalRealTime != TimeSpan.Zero);
        
            this.totalRealTime = totalRealTime;

            pitch = new Pitch();
            clock = new Clock(totalRealTime);
            ball = new Ball(pitch, pitch.Center);

            AddTimeAware(clock);
            AddTimeAware(ball);
        }

        public bool IsFinished
        {
            get { return isFinished; }
        }

        public TimeSpan TotalRealTime
        {
            get { return totalRealTime; }
        }

        public TimeSpan CurrentTime
        {
            get { return clock.CurrentTime; }
        }

        public IPitch Pitch
        {
            get { return pitch; }
        }

        public IBall Ball
        {
            get { return ball; }
        }

        public ITeam Team1
        {
            get { return team1; }
        }

        public ITeam Team2
        {
            get { return team2; }
        }

        public IEnumerable<IPlayer> Players
        {
            get { return Enumerable.Concat(team1.Players, team2.Players); }
        }
        
        public void Update(float elapsedTime)
        {
            foreach (ITimeAware timeAware in timeAwares)
            {
                timeAware.Update(elapsedTime);
            }

            if (clock.CurrentTime > totalGameTime)
            {
                isFinished = true;
            }
        }

        public void AddTeams(ITeam team1, ITeam team2)
        {
            Contract.Requires(Team1 == null);
            Contract.Requires(Team2 == null);
            Contract.Requires(team1 != null);
            Contract.Requires(team2 != null);
            Contract.Requires(team1.Side != team2.Side);

            this.team1 = team1;
            this.team2 = team2;

            AddTimeAware(team1);
            AddTimeAware(team2);
        }

        public void AddTimeAware(ITimeAware timeAware)
        {
            Contract.Requires(timeAware != null);

            timeAwares.Add(timeAware);
        }
    }
}
